package br.ufc.great.dtx.server.console;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.WindowConstants;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

import br.ufc.great.dtx.server.DTXOutput;
import br.ufc.great.dtx.server.DTXStart;
import br.ufc.great.dtx.server.config.Config;

/**
 *
 * @author Leonardo Oliveira Moreira
 * 
 * 
 */
public class DTXConsole extends javax.swing.JFrame implements WindowListener  {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -5875231850115013056L;
	private DTXOutput output;
    
	{
		output = new br.ufc.great.dtx.server.DTXOutput() {
			@Override
			public void exit() {
				DTXStart.stopDTXServer();
				DTXStart.stopTransactionManager();
				DTXStart.stopDataManager();
				System.exit(0);
			}

			@Override
			public void print(String message, int type) {
				synchronized (jtpLog) {
					addLog(message, type);					
				}
			}

			@Override
			public void print(String name, String message, int type) {
				synchronized (jtpLog) {
					addLog(name, message, type);
				}
			}

			@Override
			public void setNumberLocks(int locks) {
				synchronized (jlNumberLocks) {
					jlNumberLocks.setText("LK: " + locks);
				}
			}

			@Override
			public void setTransactionBufferSize(int size) {
				synchronized (jlTransactionBufferSize) {
					jlTransactionBufferSize.setText("TR: " + size);
				}
			}

			@Override
			public void setRemoteMessageBufferSize(int size) {
				synchronized (jlRMBufferSize) {
					jlRMBufferSize.setText("RM: " + size);
				}
			}

			@Override
			public void setRemoteOperationBufferSize(int size) {
				synchronized (jlROBufferSize) {
					jlROBufferSize.setText("RO: " + size);
				}
			}

		};
    }

    public DTXConsole() {
        jspLog = new javax.swing.JScrollPane();
        jtpLog = new javax.swing.JTextPane();
        jtToolBar = new javax.swing.JToolBar();
        jbStart = new javax.swing.JButton();
        jbStop = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JToolBar.Separator();
        jbClear = new javax.swing.JButton();
        jbSave = new javax.swing.JButton();
        jSeparator2 = new javax.swing.JToolBar.Separator();
        jlStatus = new javax.swing.JLabel();
        jSeparator3 = new javax.swing.JToolBar.Separator();
        jlNumberLocks = new javax.swing.JLabel("LK: " + 0);
        jSeparator4 = new javax.swing.JToolBar.Separator();
        jlTransactionBufferSize = new javax.swing.JLabel("TR: " + 0);
        jSeparator5 = new javax.swing.JToolBar.Separator();
        jlROBufferSize = new javax.swing.JLabel("RO: " + 0);
        jSeparator6 = new javax.swing.JToolBar.Separator();
        jlRMBufferSize = new javax.swing.JLabel("RM: " + 0);
    }
    
    public void build() {
        setName("jfMain");

        jspLog.setViewportView(jtpLog);

        jtToolBar.setRollover(true);
        
        jbStart.setIcon(new javax.swing.ImageIcon(getClass().getResource("start.png")));
        jbStart.setText("Start");
        jbStart.setFocusable(false);
        jbStart.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jbStart.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jbStart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbStartActionPerformed(evt);
            }
        });
        jtToolBar.add(jbStart);

        jbStop.setIcon(new javax.swing.ImageIcon(getClass().getResource("stop.png")));
        jbStop.setText("Stop");
        jbStop.setEnabled(false);
        jbStop.setFocusable(false);
        jbStop.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jbStop.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jbStop.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbStopActionPerformed(evt);
            }
        });
        jtToolBar.add(jbStop);
        jtToolBar.add(jSeparator1);

        jbClear.setIcon(new javax.swing.ImageIcon(getClass().getResource("clear.png")));
        jbClear.setText("Clear");
        jbClear.setEnabled(false);
        jbClear.setFocusable(false);
        jbClear.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jbClear.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jbClear.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbClearActionPerformed(evt);
            }
        });
        jtToolBar.add(jbClear);

        jbSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("save.png")));
        jbSave.setText("Save");
        jbSave.setEnabled(false);
        jbSave.setFocusable(false);
        jbSave.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jbSave.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jbSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbSaveActionPerformed(evt);
            }
        });
        jtToolBar.add(jbSave);
        jtToolBar.add(jSeparator2);

        jlStatus.setIcon(new javax.swing.ImageIcon(getClass().getResource("stoped.png")));
        jlStatus.setText("Stoped");
        jtToolBar.add(jlStatus);
        
        jtToolBar.add(jSeparator3);
        jtToolBar.add(jlNumberLocks);
        jtToolBar.add(jSeparator4);
        jtToolBar.add(jlTransactionBufferSize);
        jtToolBar.add(jSeparator5);
        jtToolBar.add(jlROBufferSize);
        jtToolBar.add(jSeparator6);
        jtToolBar.add(jlRMBufferSize);

    	addWindowListener(this);
		setTitle("DTX - Distributed Transaction on XML - [" + Config.DTX_SERVER_HOST + ":" + Config.DTX_SERVER_PORT +"]");

		setSize(640, 480);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
		
        StyledDocument styledDoc = jtpLog.getStyledDocument();
        
        styleTime = styledDoc.addStyle("time", null);
        StyleConstants.setBold(styleTime, true);
        StyleConstants.setForeground(styleTime, Color.GRAY);
        
        styleMessage = styledDoc.addStyle("message", null);
        StyleConstants.setForeground(styleMessage, Color.BLACK);

        styleRemoteMessage = styledDoc.addStyle("remoteMessage", null);
        StyleConstants.setForeground(styleRemoteMessage, Color.MAGENTA);

        styleError = styledDoc.addStyle("error", null);
        StyleConstants.setForeground(styleError, Color.RED);
        
        styleName = styledDoc.addStyle("name", null);
        StyleConstants.setForeground(styleName, Color.BLACK);
        StyleConstants.setBold(styleName, true);

        styleHighlight = styledDoc.addStyle("highlight", null);
        StyleConstants.setForeground(styleHighlight, Color.BLUE);
        StyleConstants.setBold(styleHighlight, true);

        styleTest = styledDoc.addStyle("test", null);
        StyleConstants.setForeground(styleTest, Color.PINK);
        StyleConstants.setBold(styleTest, false);

        jtpLog.setEditable(false);
		
		setLayout(new BorderLayout());
		
		add(jtToolBar, BorderLayout.NORTH);
		add(jspLog, BorderLayout.CENTER);
    }

    private void jbStartActionPerformed(java.awt.event.ActionEvent evt) {
		String port = JOptionPane.showInputDialog("Enter a port connection", String.valueOf(Config.DTX_SERVER_PORT));
    	if (port != null && port.trim().length() > 0) {
    		Config.DTX_SERVER_PORT = Integer.parseInt(port);
    	}
    	setTitle("DTX - Distributed Transaction on XML - [" + Config.DTX_SERVER_HOST + ":" + Config.DTX_SERVER_PORT +"]");
    	DTXStart.startDataManager();
    	DTXStart.startTransactionManager();
    	DTXStart.startDTXServer();
    	jbStop.setEnabled(true);
    	jbStart.setEnabled(false);
        jlStatus.setIcon(new javax.swing.ImageIcon(getClass().getResource("started.png")));
        jlStatus.setText("Started");
    }

    private void jbStopActionPerformed(java.awt.event.ActionEvent evt) {
    	DTXStart.stopDTXServer();
    	DTXStart.stopTransactionManager();
    	DTXStart.stopDataManager();
    	jbStart.setEnabled(true);
    	jbStop.setEnabled(false);
        jlStatus.setIcon(new javax.swing.ImageIcon(getClass().getResource("stoped.png")));
        jlStatus.setText("Stoped");
    }

    private void jbClearActionPerformed(java.awt.event.ActionEvent evt) {
    	jtpLog.setText("");
    	jbClear.setEnabled(false);
    	jbSave.setEnabled(false);
    }

    private void jbSaveActionPerformed(java.awt.event.ActionEvent evt) {
        JFileChooser fileChooser = new JFileChooser();
        int result = fileChooser.showSaveDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
        	File file = fileChooser.getSelectedFile();
        	try {
            	file.createNewFile();
        		PrintWriter writer = new PrintWriter(file);
        		writer.print(jtpLog.getText());
        		writer.flush();
        		writer.close();
			}
        	catch (FileNotFoundException e) {
				addLog(e.getMessage(), DTXOutput.ERROR);
			}
        	catch (IOException e) {
				addLog(e.getMessage(), DTXOutput.ERROR);
			}
        }
    }
    
    private javax.swing.JToolBar.Separator jSeparator1;
    private javax.swing.JToolBar.Separator jSeparator2;
    private javax.swing.JToolBar.Separator jSeparator3;
    private javax.swing.JToolBar.Separator jSeparator4;
    private javax.swing.JToolBar.Separator jSeparator5;
    private javax.swing.JToolBar.Separator jSeparator6;
    private javax.swing.JButton jbClear;
    private javax.swing.JButton jbSave;
    private javax.swing.JButton jbStart;
    private javax.swing.JButton jbStop;
    private javax.swing.JLabel jlStatus;
    private javax.swing.JScrollPane jspLog;
    private javax.swing.JToolBar jtToolBar;
    private javax.swing.JTextPane jtpLog;
    private javax.swing.JLabel jlNumberLocks;
    private javax.swing.JLabel jlTransactionBufferSize;
    private javax.swing.JLabel jlROBufferSize;
    private javax.swing.JLabel jlRMBufferSize;
 
    private Style styleMessage, styleTime, styleError, styleRemoteMessage, styleName, styleHighlight, styleTest;
    
	@Override
	public void windowActivated(WindowEvent e) {
		
	}

	@Override
	public void windowClosed(WindowEvent e) {

	}

	@Override
	public void windowClosing(WindowEvent e) {
		int result = JOptionPane.showConfirmDialog(null, "Exit DTX?", "Confirm Exit", JOptionPane.YES_NO_CANCEL_OPTION);
		if (result == JOptionPane.YES_OPTION)
			synchronized (output) {
				output.exit();
			}
	}

	@Override
	public void windowDeactivated(WindowEvent e) {
		
	}

	@Override
	public void windowDeiconified(WindowEvent e) {
		
	}

	@Override
	public void windowIconified(WindowEvent e) {
		
	}

	@Override
	public void windowOpened(WindowEvent e) {
		
	}
	
	public DTXOutput getOutput() {
		return output;
	}
	
	public void addLog(String message, int type) {
        StyledDocument styledDoc = jtpLog.getStyledDocument();
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM hh:mm:ss.SSS");
		String date = "[" + dateFormat.format(new Date()) + "] ";
        try {
        	styledDoc.insertString(0, date, styleTime);
        	switch (type) {
	        	case DTXOutput.ERROR : {
	        		styledDoc.insertString(date.length(), message + "\n", styleError);
	        		break;
	        	}
	        	case DTXOutput.MESSAGE : {
	        		styledDoc.insertString(date.length(), message + "\n", styleMessage);
	        		break;
	        	}
	        	case DTXOutput.REMOTE_MESSAGE : {
	        		styledDoc.insertString(date.length(), message + "\n", styleRemoteMessage);
	        		break;
	        	}
	        	case DTXOutput.HIGHLIGHT : {
	        		styledDoc.insertString(date.length(), message + "\n", styleHighlight);
	        		break;
	        	}
	        	case DTXOutput.TEST : {
	        		styledDoc.insertString(date.length(), message + "\n", styleTest);
	        		break;
	        	}
        	}
        	jtpLog.setCaretPosition(0);
        	jbClear.setEnabled(true);
        	jbSave.setEnabled(true);
        } 
        catch (BadLocationException e) {
            
        }
	}
	
	public void addLog(String name, String message, int type) {
        StyledDocument styledDoc = jtpLog.getStyledDocument();
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM hh:mm:ss.SSS");
		String date = "[" + dateFormat.format(new Date()) + "] ";
        try {
        	styledDoc.insertString(0, date, styleTime);
        	styledDoc.insertString(date.length(), name + ": ", styleName);
        	switch (type) {
	        	case DTXOutput.ERROR : {
	        		styledDoc.insertString((name.length() + date.length() + 2), message + "\n", styleError);
	        		break;
	        	}
	        	case DTXOutput.MESSAGE : {
	        		styledDoc.insertString((name.length() + date.length() + 2), message + "\n", styleMessage);
	        		break;
	        	}
	        	case DTXOutput.REMOTE_MESSAGE : {
	        		styledDoc.insertString((name.length() + date.length() + 2), message + "\n", styleRemoteMessage);
	        		break;
	        	}
	        	case DTXOutput.HIGHLIGHT : {
	        		styledDoc.insertString((name.length() + date.length() + 2), message + "\n", styleHighlight);
	        		break;
	        	}
	        	case DTXOutput.TEST : {
	        		styledDoc.insertString((name.length() + date.length() + 2), message + "\n", styleTest);
	        		break;
	        	}
        	}
        	jtpLog.setCaretPosition(0);
        	jbClear.setEnabled(true);
        	jbSave.setEnabled(true);
        } 
        catch (BadLocationException e) {
            
        }
	}

}
